/*
 *  Copyright (c) 2018, Infineon Technologies AG
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification,are permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *  this list of conditions and the following disclaimer in the documentation
 *  and/or other materials provided with the distribution.
 *  - Neither the name of the copyright holders nor the names of its contributors
 *  may be used to endorse or promote products derived from this software without
 *  specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 *  ARE  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 *  LIABLE  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 *  SUBSTITUTE GOODS OR  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 *  CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 *  To improve the quality of the software, users are encouraged to share
 *  modifications, enhancements or bug fixes with Infineon Technologies AG
 *  dave@infineon.com).
 */
/**
 * \defgroup controller Controller
 * @{
 */
/**
 * \file    controller_buck.h
 * \author  Manuel Escudero Rodriguez
 * \date    09.05.2018
 * \brief   Controller code
 */
#ifndef __CONTROLLER_BUCK_H_
#define __CONTROLLER_BUCK_H_

#include "controller.h"
#include "config_adc.h"
#include "config_pwm.h"
#include "config_buck_pwm.h"

/**
 * \name Fixed point compensator buck mode
 * Compensator bandwitch 3.51kHz, 53.9° phase margin 15dB gain margin for 3300W.
 * @{
 */
/** Output voltage reference value. [ADC_units] */
#define BUCK_VOLTAGE_REF 		(parameters_RAM.voltage_reference)
/** Output voltage reference value. [ADC_units] */
#define BUCK_VOLTAGE_REF_TRHLD 	(11380) // Aprox 43V
/** Output voltage reference value. [ADC_units] */
#define BUCK_VOLTAGE_REF_MIN 	(10586) // Aprox 40V
/** Fixed point format of coefficients. [bits] */
#define BUCK_Q_DECIMALS  		(14)
/** Q0.Q_DECIMALS format coefficient. */
#define BUCK_COEFF_B2    		((1 << BUCK_Q_DECIMALS) + 11469)
/** Q0.Q_DECIMALS format coefficient. */
#define BUCK_COEFF_B1    		(-((2 << BUCK_Q_DECIMALS) + 14582))
/** Q0.Q_DECIMALS format coefficient. */
#define BUCK_COEFF_B0    		((1 << BUCK_Q_DECIMALS) + 3461)
/** Fixed point format of coefficients. [bits] */
#define BUCK_Q_POLE_DECIMALS  	(5)
/** Q0.Q_POLE_DECIMALS format coefficient. */
/* This is hard coded as a 1 in the control loop */
#define BUCK_COEFF_A1    		((1 << BUCK_Q_POLE_DECIMALS) + 26)
/** Q0.Q_POLE_DECIMALS format coefficient. */
/* This is hard coded as a 0 in the control loop */
#define BUCK_COEFF_A0    		(-((0 << BUCK_Q_POLE_DECIMALS) + 26))
/** @} */

/*---------------------------------------------------------------------------*/
/**
 * \brief   Initialization of startup.
 * \return  None
 *
 *  Compensator reference is switched to the startup reference.
 *  Compensator status is reset.
 */
#ifndef DOXYGEN_SKIP
__attribute__((section(".ram_code")))
#endif
static inline void buck_start_up_init()
{
	/* Ensures synchronous rectifiers are OFF. */
    pwm_sync_stop();
    /* 
     * In case the output capacitor is still charged the initial reference 
     * would be set at that starting value. 
     */
    uint16_t actual_vo = ADC_VO_RESULT;
    if(actual_vo > START_UP_INIT)
    {
    	/*
		 * Forces at least one step of start up sequence, there are some 
		 * variables to be updated in this last step of the sequence. 
		 * See start_up_iterate().
		 */
        if(actual_vo >= BUCK_VOLTAGE_REF)
        {
            voltage_ctr.reference = BUCK_VOLTAGE_REF - START_UP_INIT;
        }
        else
        {
        	voltage_ctr.reference = actual_vo - START_UP_INIT;
        }
    }
    else
    {
        voltage_ctr.reference = START_UP_INIT;
    }
    /* Deactivation of burst during soft start */
    voltage_ctr.burst_stop_limit = 0;
    voltage_ctr.burst_high_limit = 0;
    voltage_ctr.burst_low_limit = 0;
    /* Clearing of the compensator status. */
    voltage_ctr.error[0] = 0;
    voltage_ctr.error[1] = 0;
    voltage_ctr.phase[0] = (50 << BUCK_Q_DECIMALS);
    voltage_ctr.phase[1] = (50 << BUCK_Q_DECIMALS);
    /* Reset of the soft start protection timer. */
    voltage_ctr.start_up_cnt = BUCK_START_UP_STEP_TIME;
    /* Soft start increment at low speed. */
    voltage_ctr.soft_start_inc = START_UP_LOW_INC;
    /* Minimum phase allowed during soft start */
    if(MIN_BLK < (PWM_A_B_MIN_DT + 2))
    {
    	/*
    	 * Note: +2 because of modulation scheme from peripherals miss comparison
    	 * event during startup otherwise.
    	 */
        voltage_ctr.min_phase = (PWM_A_B_MIN_DT + 2);
        voltage_ctr.burst_phase = (PWM_A_B_MIN_DT + 2);
        voltage_ctr.blk_phase = (PWM_A_B_MIN_DT + 2);    	
    }
    else
    {
        voltage_ctr.min_phase = MIN_BLK;
        voltage_ctr.burst_phase = MIN_BLK;
        voltage_ctr.blk_phase = MIN_BLK;   	
    }
    pwm_blk_set(voltage_ctr.blk_phase);
    peak_ref_set(voltage_ctr.min_phase);
    /* 
     * End of ramping up of reference during start-up. 
     * To be scaled by overpower vout derating.
     */
    voltage_ctr.reference_startup = BUCK_VOLTAGE_REF;
	/* 
	 * Initial status would be OFF.
	 * Brown in condition will start the converter in the on-off section. 
	 */
	converter_ctr.status = (START_EN | DCM | SOFT);
}
/*---------------------------------------------------------------------------*/
/**
 * \brief   Input voltage ON OFF control and remote enable feature.
 * \return  None
 */
#ifndef DOXYGEN_SKIP
__attribute__((section(".ram_code")))
#endif
static inline void buck_brown_in_off_ctr()
{
    /*
     * Keeps track of Vin. The sampling is slow enough it can measure suddenly 400V 
     * and not switch ON because is has not measured above 380 and below 390 
     * (Hysteresis for the higher and lower limit).
     */
    static uint8_t vin_track;
    
    /* Input voltage measurement update, only done here. */
    converter_ctr.adc_vin_measure = ((converter_ctr.adc_vin_measure * ADC_VIN_AVG_FACTOR) + ADC_VIN_RESULT) >> ADC_VIN_AVG_RATIO;

	/*
	 * Brown in-out could be deactivated during debugging.
	 */
	if(!parameters_RAM.debug_vin)
	{
		/* Next time Vin goes into valid range, it will be raising. */
		if(converter_ctr.adc_vin_measure < (uint32_t)VIN_MIN_LOW)
		{
			vin_track = V_RISING;
		}
		/* Next time Vin goes into valid range, it will be falling. */
		else if(converter_ctr.adc_vin_measure > (uint32_t)VIN_MAX_HIGH)
		{
			vin_track = V_FALLING;
		}
		/* If converter not already OFF check conditions for brown out. */
		if(!(converter_ctr.status & OFF))
		{
			/* Switch OFF outside of the minimum or maximum allowed running voltages */
			if((converter_ctr.adc_vin_measure < (uint32_t)VIN_MIN_LOW) || (converter_ctr.adc_vin_measure > (uint32_t)VIN_MAX_HIGH))
			{
				/* Request the converter to stop. */
				converter_ctr.status |= STOP;
			}
		}
		/* If converter is OFF check conditions for brown in. */
		else
		{
			if((vin_track == V_RISING) && (converter_ctr.adc_vin_measure < (uint32_t)VIN_MIN_LOW))
				adc_io_set_zero();
				
			/* Switch ON inside of the allowed input voltage window */
			if((vin_track == V_FALLING) && (converter_ctr.adc_vin_measure < (uint32_t)VIN_MAX_LOW) && (converter_ctr.adc_vin_measure > (uint32_t)VIN_MIN_LOW))
			{
				/* Request the converter to start. */
				converter_ctr.status |= START;
			}
			/* Switch ON inside of the allowed input voltage window */
			if((vin_track == V_RISING) && (converter_ctr.adc_vin_measure > (uint32_t)VIN_MIN_HIGH) && (converter_ctr.adc_vin_measure < (uint32_t)VIN_MAX_HIGH))
			{
				/* Request the converter to start. */
				converter_ctr.status |= START;
			}		
		}
	}
	/*---------------------------------------------------------------------------*/
    /*
     * Remote ON-OFF feature
     */
    if((converter_ctr.status & STOP) || !(converter_ctr.status & START_EN))
    {
    	converter_set_off();
    }
    /* Input voltage monitoring deactivated. */
    else if(parameters_RAM.debug_vin)
    {
        /* If no fault happened apart from a requested OFF. */
        if(!(converter_ctr.status & (STATUS_FAULT & ~OFF)) && (converter_ctr.status & OFF))
        {
			buck_start_up_init();
        }
        converter_ctr.status &= ~START;
    }
    /* Input voltage monitoring activated, start will come when voltage is within valid range. */
    else if((converter_ctr.status & START))
    {
        /* If no fault happened apart from a requested OFF */
        if(!(converter_ctr.status & (STATUS_FAULT & ~OFF)) && (converter_ctr.status & OFF))
        {
        	buck_start_up_init();
        }
        converter_ctr.status &= ~START;
    }
}
/*---------------------------------------------------------------------------*/
/**
 * \brief   Start up sequence iteration.
 * \return  None
 *
 * Ramps up output voltage reference. Converter increases output voltage in 
 * close loop. Ends of sequence when output voltage reaches nominal value.
 * Time out protection in case of overload.
 */
#ifndef DOXYGEN_SKIP
__attribute__((section(".ram_code")))
#endif
static inline void buck_start_up_iterate()
{
	static uint32_t start_up_tick; /* Start up clock divider. [control_cyc] */
	static uint16_t time_out_cnt; /* Filters time out condition. [control_cyc] */
	static uint16_t soft_start_inc_cnt; /* Step increment counter. [control_cyc] */
	
	/* Start-up time out protection timer. */
	if(converter_ctr.time_tick != start_up_tick)
	{
		if(voltage_ctr.start_up_cnt > 0)
		{
			voltage_ctr.start_up_cnt --;
		}
		start_up_tick = converter_ctr.time_tick;
	}
	/* Soft star-up routine. */
	if(converter_ctr.status & SOFT)
	{
		/* Time out protection during soft start procedure */
		if((voltage_ctr.start_up_cnt == 0) && !(converter_ctr.status & OFF))
		{
			/* Time out protection can be deactivated during debugging activities */
			if(parameters_RAM.debug_soft)
			{
				/* End of start up sequence in debugging mode. */
				voltage_ctr.reference = voltage_ctr.reference_startup;
				voltage_ctr.min_phase = BUCK_PHASE_MIN;
				voltage_ctr.burst_phase = BUCK_BURST_PHASE;
				/* Burst adjustment for different output voltages. */
				if(parameters_RAM.voltage_reference > parameters_DFLT.voltage_reference)
				{
					uint8_t incrmnt = ((parameters_RAM.voltage_reference - parameters_DFLT.voltage_reference) * 3) >> 7;
					voltage_ctr.burst_stop_limit = BUCK_BURST_STOP_LIMIT + incrmnt;
					voltage_ctr.burst_high_limit = BUCK_BURST_HIGH_LIMIT + incrmnt;
					voltage_ctr.burst_low_limit = BUCK_BURST_LOW_LIMIT + incrmnt;
				}
				else
				{
					voltage_ctr.burst_stop_limit = BUCK_BURST_STOP_LIMIT;
					voltage_ctr.burst_high_limit = BUCK_BURST_HIGH_LIMIT;
					voltage_ctr.burst_low_limit = BUCK_BURST_LOW_LIMIT;
				}
				converter_ctr.status &= ~SOFT;
			}
			/* Latching protection due to possible overload. */
			else if(time_out_cnt > 100)
			{
				converter_ctr.status |= START_FAIL;
				TRAP_SET();
			}
			else
			{
				/* Forces an increment in the reference to avoid the plateau. */
				time_out_cnt ++;
				/* Resets time out timer. */
				voltage_ctr.start_up_cnt = BUCK_START_UP_STEP_TIME;
			}
		}
		/*
		 * Next step will happen after reaching or going over the actual step.
		 * Next step could be forced by first time out during start up, in case of heavy load.
		 */
		if(ADC_VO_RESULT >= voltage_ctr.reference)
		{
			/* Increment reference only in case no fault is active */
			if(!(converter_ctr.status & STATUS_FAULT))
			{
				if(voltage_ctr.reference > START_UP_LOW_THRSHLD)
				{
					/* Minimum step size. */
					if(voltage_ctr.soft_start_inc < START_UP_LOW_INC) 
					{
						voltage_ctr.soft_start_inc = START_UP_LOW_INC;
					}
					voltage_ctr.reference += voltage_ctr.soft_start_inc;
					
					/* Ramp up the step size. */
					if(voltage_ctr.soft_start_inc > START_UP_LOW_INC) 
					{
						/* Smoother change of step increment. */
						if(soft_start_inc_cnt > 0)
						{
							soft_start_inc_cnt --;
						}
						else
						{
							voltage_ctr.soft_start_inc --;
							soft_start_inc_cnt = START_UP_INC_CNT;
						}
					}
				}
				else
				{
					/* Slow step size when output cap is totally discharged. */
					voltage_ctr.soft_start_inc = BUCK_START_UP_INC;
					voltage_ctr.reference += voltage_ctr.soft_start_inc;
				}
			}
			/* End of start up sequence. */
			if(voltage_ctr.reference >= voltage_ctr.reference_startup)
			{
				/* Set of normal mode coefficients. */
				voltage_ctr.reference = voltage_ctr.reference_startup;
				voltage_ctr.min_phase = BUCK_PHASE_MIN;
				voltage_ctr.burst_phase = BUCK_BURST_PHASE;
				/* Burst adjustment for different output voltages. */
				if(parameters_RAM.voltage_reference > parameters_DFLT.voltage_reference)
				{
					uint8_t incrmnt = ((parameters_RAM.voltage_reference - parameters_DFLT.voltage_reference) * 3) >> 7;
					voltage_ctr.burst_stop_limit = BUCK_BURST_STOP_LIMIT + incrmnt;
					voltage_ctr.burst_high_limit = BUCK_BURST_HIGH_LIMIT + incrmnt;
					voltage_ctr.burst_low_limit = BUCK_BURST_LOW_LIMIT + incrmnt;
				}
				else
				{
					voltage_ctr.burst_stop_limit = BUCK_BURST_STOP_LIMIT;
					voltage_ctr.burst_high_limit = BUCK_BURST_HIGH_LIMIT;
					voltage_ctr.burst_low_limit = BUCK_BURST_LOW_LIMIT;
				}
				/* Output voltage protections ON */
				UVP_ON();
				XMC_VADC_GROUP_SetBoundaries(VADC_G0, VOLTAGE_UVP << XMC_VADC_RESULT_LEFT_ALIGN_10BIT, VOLTAGE_OVP);
				converter_ctr.status &= ~SOFT;
				time_out_cnt = 0;
			}
			/* Resets time out timer. */
			voltage_ctr.start_up_cnt = BUCK_START_UP_STEP_TIME;
		}
		/*
		 * If soft start is deactivated during debugging activities, 
		 * still output voltage range protection will work after reaching the 
		 * nominal output voltage.
		 */
		if(parameters_RAM.debug_soft)
		{
			/*
			 * Activates the output voltage protections after the reference voltage
			 * is reached.
			 */
			if(ADC_VO_RESULT >= voltage_ctr.reference_startup)
			{
				UVP_ON();
				XMC_VADC_GROUP_SetBoundaries(VADC_G0, VOLTAGE_UVP << XMC_VADC_RESULT_LEFT_ALIGN_10BIT, VOLTAGE_OVP);
				converter_ctr.status &= ~SOFT;
			}
		}
	}
	/*
	 * Degugging Rg
	 */
//	static uint16_t rg_debug_timeout;
//	if(!(converter_ctr.status & SOFT))
//	{
//		if(rg_debug_timeout > 3000)
//		{
//			converter_ctr.status |= START_FAIL;
//			TRAP_SET();
//		}
//		else
//		{
//			rg_debug_timeout ++;
//		}
//	}
	/*
	 * Debugging Rg
	 */
}
/*---------------------------------------------------------------------------*/
/**
 * \brief   Iteration of the voltage control loop
 * \return  None
 * \todo    Separate active burst control from control loop iteration to execute control at higher frequency.
 */
#ifndef DOXYGEN_SKIP
__attribute__((section(".ram_code")))
#endif
static inline void buck_voltage_ctr_iterate()
{
	static uint16_t burst_in_cnt; /* Burst enter filter counter. [control_cyc] */
	static uint16_t burst_out_cnt; /* Burst exit filter counter. [control_cyc] */
	static uint16_t synch_on_cnt; /* Filters synchronous ON after trap conditions. [control_cyc] */
	static uint16_t burst; /* Burst skipping length sequence counter. [control_cyc] */
	int32_t phase; /* New output of compensator. [Q0.Q_DECIMALS] */
	static uint16_t burst_filter =2;
	
    /* Q0 value */
    int32_t voltage_error = (int32_t) voltage_ctr.reference - ADC_VO_RESULT;	
	// voltage_error_voltage_ctr = voltage_error;

    /* Compensator calculations. Q0.Q_DECIMALS result */
    phase = (BUCK_COEFF_B2 * voltage_error) + (BUCK_COEFF_B1 * voltage_ctr.error[0]) + (BUCK_COEFF_B0 * voltage_ctr.error[1]) + \
    		(((BUCK_COEFF_A1 * voltage_ctr.phase[0]) + (BUCK_COEFF_A0 * voltage_ctr.phase[1])) >> BUCK_Q_POLE_DECIMALS);
	/* Lower saturation. */
	if(phase < (PWM_PEAK_REF_MIN << BUCK_Q_DECIMALS))
	{
		phase = (PWM_PEAK_REF_MIN << BUCK_Q_DECIMALS);
	}
	/* Upper saturation. */
	else if(phase > (int32_t) (PWM_PEAK_REF_MAX << BUCK_Q_DECIMALS))
	{
		phase = (int32_t) (PWM_PEAK_REF_MAX << BUCK_Q_DECIMALS);
	}
    /* PWM update value comes from the integer part of the compensator output. */
    uint16_t phase_out = (phase >> BUCK_Q_DECIMALS);
    phase_out_test = phase_out;
    /*
     * PWM update value under burst_low_limit will make converter go into
     * burst mode. To exit burst PWM update value may increase above burst_high_limit.
     */
	if((voltage_error > 8) || (voltage_error < (-8)))
	{

		if(!(converter_ctr.status & OFF))
		{	
			if((voltage_error > 8) && (burst_filter ==0))
			{
				voltage_ctr.reference -=1;
				burst_filter = 2;
			}
	// 		if((voltage_error < (-265)) && (burst_filter ==0))
	// 		{
	// 			voltage_ctr.reference +=1;
	// 			burst_filter = 5;
	// 		}
	// 		if(voltage_ctr.reference < 12900)
	// 			voltage_ctr.reference = 12900;
	// 		if(voltage_ctr.reference > 12990)
	// 			voltage_ctr.reference = 12990;

			if(burst_filter > 0)
				burst_filter--;

		}
	}

    if((phase_out < voltage_ctr.burst_low_limit) || ((converter_ctr.status & BURST) && (phase_out < voltage_ctr.burst_high_limit)))
    {
    	/* Burst mode condition entrance is filtered. */
        if(burst_in_cnt == 0)
        { 
            /* Coming from normal mode some settings are required. */
            if(!(converter_ctr.status & BURST) || !(BURST_CNT.ccu4_handle->slice_ptr->TCST & CCU4_CC4_TCST_TRB_Msk))
            {
            	/* Burst mode starts with a trapping cycle. */
                TRAP_SET();
                /* Starts burst counter. */
                XMC_CCU4_SLICE_ClearTimer(BURST_CNT.ccu4_handle->slice_ptr);
                XMC_CCU4_SLICE_StartTimer(BURST_CNT.ccu4_handle->slice_ptr);
                /* In burst mode synchronous rectifiers will be off. */
                pwm_sync_stop();
                burst = BURST_TRAP_CYC;
                converter_ctr.status |= BURST;
            }
        }
        else
        {
            burst_in_cnt--;
        }
        /* Using different minimum phase values for burst. */
        if (converter_ctr.status & BURST)
        {
            /* Limit minimum level of shift. */
            if (phase_out < voltage_ctr.burst_phase)
            {
                voltage_ctr.phase_out = voltage_ctr.burst_phase;
            }
            else
            {
                voltage_ctr.phase_out = phase_out;
            }
        }
        else
        {
        	/* Limit control signal may help avoiding hard switching. */
			if (phase_out < voltage_ctr.min_phase)
			{
				voltage_ctr.phase_out = voltage_ctr.min_phase;
			}
			else
			{
				voltage_ctr.phase_out = phase_out;
			}
        }             
        /* Control of number of skipped cycles during burst. */
        if(TRAP_ON)
        {
        	/* Under a minimum PWM update value there is no switching (no load). */
            if((burst == 0) && (phase_out > voltage_ctr.burst_stop_limit))
            {
                /* Resets burst counter */
                XMC_CCU4_SLICE_ClearTimer(BURST_CNT.ccu4_handle->slice_ptr);
                /* No faults active to continue switching. */
                if(!(converter_ctr.status & STATUS_FAULT))
                {
                	TRAP_RST();     
                }
                burst = BURST_TRAP_CYC;
            }
            else if(burst > 0)
            {
                burst --;
            }
        }
        /* Adjustment of secondary rectifiers duty cycle. */
        buck_pwm_sync_shift();
        burst_out_cnt = BURST_OUT_CYC;
    }
    else
    {
    	/* Burst exit condition is filtered. */
        if(burst_out_cnt == 0)
        {
            /* Coming from burst mode some preparatives are required. */
            if((converter_ctr.status & BURST) || (BURST_CNT.ccu4_handle->slice_ptr->TCST & CCU4_CC4_TCST_TRB_Msk))
            {
                /* Stops and clears burst timer. */
            	BURST_CNT.ccu4_handle->slice_ptr->TCCLR = ((uint32_t) CCU4_CC4_TCCLR_TRBC_Msk);
                converter_ctr.status &= ~BURST;
            }
            /* No faults active to continue switching. */
            if((!(converter_ctr.status & STATUS_FAULT)) && TRAP_ON)
            {
            	TRAP_RST();
            }
        }
        else
        {
            burst_out_cnt --;
        }
        voltage_ctr.phase_out = phase_out;
        /* Adjustment of secondary rectifiers duty cycle. */
        buck_pwm_sync_shift();
        burst_in_cnt = BURST_IN_CYC;
    }
    
    /* Switching ON secondary rectifiers. */
	if((!(converter_ctr.status & SYNC_OFF)) && !TRAP_ON)
	{
		if(synch_on_cnt > 0)
		{
			synch_on_cnt --;
		}
		else
		{
			buck_pwm_sync_start();
		}
	}
	else
	{
		synch_on_cnt = SYNCH_ON_CNT;
	}
	
    /* Update PWM signals with new values */
    buck_pwm_shift();
    /* Update of error buffer. */
    voltage_ctr.error[1] = voltage_ctr.error[0];
    voltage_ctr.error[0] = voltage_error;
    /* Storage of current output of the compensator for next iteration. */
    voltage_ctr.phase[1] = voltage_ctr.phase[0];
    voltage_ctr.phase[0] = phase;
}
/*---------------------------------------------------------------------------*/
/**
 * \brief   Iteration of the current control loop
 * \return  None
 */
#ifndef DOXYGEN_SKIP
__attribute__((section(".ram_code")))
#endif
static inline void buck_current_ctr_iterate()
{
	static uint16_t hiccup_in_cnt; /* Timing for entering hiccup mode. [control_cyc] */
	static uint32_t hiccup_out_cnt; /* Timing for exiting hiccup mode. [control_cyc] */
	static uint16_t dcm_in_cnt; /* Timing for entering DCM mode. [control_cyc] */
	static uint16_t dcm_out_cnt; /* Timing for exiting DCM mode. [control_cyc] */
	int16_t adc_io_measure; /* [ADC_units] */
	/* 
	 * Average filtering of the input current measurement.
	 * Note: Notice the hysteresis due to the shift. Fix storing all decimals if bigger ratio is used. 
	 */
    current_ctr.adc_il_measure = ((current_ctr.adc_il_measure * ADC_IL_AVG_FACTOR) + ADC_IL_RESULT) >> ADC_IL_AVG_RATIO;
    adc_io_measure = ADC_IO_RESULT - current_ctr.adc_io_zero;
    if(adc_io_measure < 0)
    {
    	adc_io_measure = 0;
    }
    current_ctr.adc_io_measure = ((current_ctr.adc_io_measure * ADC_IO_AVG_FACTOR) + (adc_io_measure << 1)) >> ADC_IO_AVG_RATIO;
    /*
     * Over power protection
     */
    if((current_ctr.adc_io_measure > current_ctr.hiccup_io_limit) || (current_ctr.ovp_state))
    {
        /* If the current has been higher than the hiccup limit for several iterations trigger the protection. */
        if(hiccup_in_cnt == 0)
        {
            /* Switches off the short circuit protection in prevention of a false triggering during hiccup sequence */
            UVP_OFF();
            OVP_OFF();
            TRAP_SET();
            converter_ctr.status |= HICCUP_FAIL;
            /* Resets the filter for exiting the hiccup condition */
            hiccup_out_cnt = (uint32_t)HICCUP_OUT_CNT_LIM;
        }
        else
        {
            hiccup_in_cnt --;
        }
    }
    else
    {
        /* Hiccup condition was reached previously */
        if(converter_ctr.status & HICCUP_FAIL)
        {
            /* If the current have been lower than the hiccup limit for certain number of iterations, exits trap. */
            if(hiccup_out_cnt == 0)
            {
            	/* No other fault than HICCUP happened. */
            	if(!(converter_ctr.status & (STATUS_FAULT & ~HICCUP_FAIL)))
            	{
            		buck_start_up_init();
                	converter_ctr.status &= ~HICCUP_FAIL;
            	}
            	/* Some other fault active, just remove the HICCUP_FAIL. */
            	else
            	{
            		converter_ctr.status &= ~HICCUP_FAIL;
            	}
            }
            else
            {
                hiccup_out_cnt --;
            }
        }
        /* Filter of Hiccup condition entrance. */
        if(hiccup_in_cnt < HICCUP_IN_CNT_LIM)
        {
        	hiccup_in_cnt ++;
        }
    }
    /*---------------------------------------------------------------------------*/
    /*
     * Synchronous modes: OFF, DCM or Normal mode selection.
     */
    if((current_ctr.adc_io_measure < DCM_ENTER_LIM))
    {
        /* If the current has been lower than the DCM limit for several iterations, sets the flag. */
        if(dcm_in_cnt == 0)
        {
        	/* Synchronous in DCM mode under threshold load. */
        	if(!(converter_ctr.status & DCM))
        	{
        		buck_pwm_sync_dcm();
        	}
        	converter_ctr.status |= DCM;
        }
        else
        {
            dcm_in_cnt --;
        }
        /* Reset the filter for exiting the DCM condition */
        dcm_out_cnt = DCM_OUT_CNT_LIM;
    }
    else if(current_ctr.adc_io_measure > (uint32_t) DCM_EXIT_LIM)
    {  
        /*
         * Forces synchronous to be working in DCM mode for some cycles before going into normal mode.
         * This helps a progressive increase of the synchronous conduction time.
         */
        if(!(converter_ctr.status & SYNC_ICP))
        {
        	/* If the current have been higher than the DCM limit for certain number of iteration, clears the flag. */
			if(dcm_out_cnt == 0)
			{
				/* Synchronous in standard mode over threshold. */
				if(converter_ctr.status & DCM)
				{
					buck_pwm_sync_standard();
				}
				converter_ctr.status &= ~DCM;
			}
			else
			{
				dcm_out_cnt --;
			}
        }
        else
        {
        	/* Reset the filter for exiting DCM condition */
			dcm_out_cnt = DCM_OUT_CNT_LIM;
        }
        /* Reset the filter for entering DCM condition */
        dcm_in_cnt = DCM_IN_CNT_LIM;
    }    
}
/*---------------------------------------------------------------------------*/
/**
 * \brief       Constant power limitation curve control.
 * \return      None
 */
#ifndef DOXYGEN_SKIP
__attribute__((section(".ram_code")))
#endif
static inline void buck_power_limit_ctr()
{
	static uint32_t ovp_vout_tick; /* Filter of Vout decrement on overpower event. */
	static uint32_t ovp_vout_strp_tick; /* Filter of Vout decrement on overpower event. */
	static uint16_t ovp_vout_dec_cnt; /* Filter of Vout decrement on overpower event. */
	static uint16_t ovp_vout_inc_cnt; /* Filter of Vout increment on overpower event resume. */
    static uint16_t ovcrr_hiccup_in_cnt; /* Filter of overcurrent event. */
    static uint32_t ovpwr_hiccup_in_cnt; /* Filter of overpower event. */
    uint16_t reference_new; /* New calculated Vout reference to keep power limitation at output. */
    int32_t adc_ovp_error; /* Output power measure result of vout_reference * adc_io_measure. [ADC units] */
 int16_t adc_io_measure; /* [ADC_units] */   	
	/*
	 * During soft start the end of the ramp up voltage is derated by the
	 * estimated power will be delivered at the end of the soft start.
	 * To end start up at the voltage we will be regulating because of the fixed
	 * power limitation. 
	 */
	if(converter_ctr.status & SOFT)
	{
		/* Synchronous to control IRQ timer. */
		if((converter_ctr.time_tick >> OVP_VOUT_PRSCLR_STRP) != ovp_vout_strp_tick)
		{
			/* Estimation of output power. */
			adc_ovp_error = (current_ctr.adc_io_measure * voltage_ctr.reference_startup) - (uint32_t)OVPWR_LIM;

			// adc_io_measure_power_test = current_ctr.adc_io_measure;
			// reference_startup_power_test = voltage_ctr.reference_startup;

			
			// if(adc_ovp_error < 0)
			// {
			// 	adc_ovp_error_test = -adc_ovp_error;
			// 	adc_ovp_error_PN_flag = 1;
			// }
			// else
			// {
			// 	adc_ovp_error_PN_flag = 0;
			// 	adc_ovp_error_test = adc_ovp_error;
			// }

			/* Derating of output voltage in output overpower event. */
			if(adc_ovp_error > 0)
			{    	
				/* Decrease voltage reference, never under the minimum allowed. */
				voltage_ctr.reference_startup -= OVP_VOUT_STEP_STRP;
				if(voltage_ctr.reference_startup < BUCK_VOLTAGE_REF_MIN)
				{
					voltage_ctr.reference_startup = BUCK_VOLTAGE_REF_MIN;
				}
			}
			/* Hysteresis to go back to the original level. */
			else if(adc_ovp_error < -(OVPWR_LIM_HYST))
			{
				/* 
				 * BUCK_VOLTAGE_REF is the final fixed reference voltage. Never to
				 * regulate above this level.
				 */
				voltage_ctr.reference_startup += OVP_VOUT_STEP_STRP;
				if(voltage_ctr.reference_startup > BUCK_VOLTAGE_REF)
				{
					voltage_ctr.reference_startup = BUCK_VOLTAGE_REF;
				}
			}
			/* Reset of overcurrent flag to allow restart. */
			ovcrr_hiccup_in_cnt = OVCRR_HICCUP_IN_CNT_LIM;		
			/* 
			 * Note: This line initializes overpower detection time limit after 
			 * a soft start. It might be desired that converter has to run for 
			 * some time in normal conditions before settling this limit, then 
			 * remove this line.
			 */
			ovpwr_hiccup_in_cnt = OVPWR_HICCUP_IN_CNT_LIM;
			/* Synchronous with control IRQ timer. */
			ovp_vout_strp_tick = (converter_ctr.time_tick >> OVP_VOUT_PRSCLR_STRP);
		}
	}
	/* Vout derating while converter is running to limit maximum power. */
	else if(!(converter_ctr.status & STATUS_FAULT))
	{
		/* Synchronous to control IRQ timer. */
		if((converter_ctr.time_tick >> OVP_VOUT_PRSCLR) != ovp_vout_tick)
		{
			/* Estimation of output power. */
			adc_ovp_error = (current_ctr.adc_io_measure * voltage_ctr.reference) - (uint32_t)OVPWR_LIM;
			// adc_ovp_error = (current_ctr.adc_io_measure * voltage_ctr.reference) - (3558667);
			// adc_ovp_error = (current_ctr.adc_io_measure * voltage_ctr.reference) - (11893335);
    // adc_io_measure = ADC_IO_RESULT - current_ctr.adc_io_zero;
    // if(adc_io_measure < 0)
    // {
    // 	adc_io_measure = 0;
    // }
	// adc_ovp_error = (adc_io_measure * voltage_ctr.reference) - (uint32_t)OVPWR_LIM;

			// adc_io_measure_power_test = adc_io_measure;
			adc_io_measure_power_test = current_ctr.adc_io_measure;
			reference_startup_power_test = voltage_ctr.reference;

			
			if(adc_ovp_error < 0)
			{
				adc_ovp_error_test = -adc_ovp_error;
				adc_ovp_error_PN_flag = 1;
			}
			else
			{
				adc_ovp_error_PN_flag = 0;
				adc_ovp_error_test = adc_ovp_error;
			}
			
			/* Derating of output voltage in output overpower event. */
			if(adc_ovp_error > 0)
			{    	
				if(ovp_vout_dec_cnt == 0)
				{
					reference_new = voltage_ctr.reference - (adc_ovp_error >> OVP_P_DEC_FCTR) - 1;
					/* Decrease voltage reference, never under the minimum. */
					if(reference_new > BUCK_VOLTAGE_REF_MIN)
					{
						voltage_ctr.reference = reference_new;
					}
					else
					{
						voltage_ctr.reference = BUCK_VOLTAGE_REF_MIN;
						/* 
						 * If the output current has been higher than the limit 
						 * for several iterations triggers the protection.
						 * Voltage does not decrease under minimum. 
						 */
						if(ovcrr_hiccup_in_cnt == 0)
						{
							current_ctr.ovp_state = true;
						}
						else
						{
							ovcrr_hiccup_in_cnt --;
						}
					}
					ovp_vout_dec_cnt = OVP_VOUT_DLY;
				}
				else
				{
					ovp_vout_dec_cnt --;
				} 
			}
			/* Hysteresis to go back to the original level. */
			else if(adc_ovp_error < -(OVPWR_LIM_HYST))
			{
				if(ovp_vout_inc_cnt == 0)
				{
					// reference_new = voltage_ctr.reference + ((-adc_ovp_error) >> OVP_P_INC_FCTR) + 1;
					voltage_error_voltage_ctr = (int32_t) voltage_ctr.reference - ADC_VO_RESULT;
					if(voltage_error_voltage_ctr < 4)
						// reference_new = voltage_ctr.reference + 4;
						reference_new = voltage_ctr.reference + ((-adc_ovp_error) >> OVP_P_INC_FCTR) + 4;
					else
						reference_new = voltage_ctr.reference;
					// reference_new_test = reference_new;
					// reference_power_test = voltage_ctr.reference;
					// ADC_VO_RESULT_power_test = ADC_VO_RESULT;
					
					/* BUCK_VOLTAGE_REF is the final fixed reference voltage. */
					if(reference_new < BUCK_VOLTAGE_REF)
					{
						voltage_ctr.reference = reference_new;
					}
					else
					{
						voltage_ctr.reference = BUCK_VOLTAGE_REF;
					}
					ovp_vout_inc_cnt = OVP_VOUT_DLY;
				}
				else
				{
					ovp_vout_inc_cnt --;
				}
				/* Filter of hiccup condition entrance. */
				if(ovcrr_hiccup_in_cnt < OVCRR_HICCUP_IN_CNT_LIM)
				{
					ovcrr_hiccup_in_cnt ++;
				}
			}
			else
			{
				ovp_vout_inc_cnt = OVP_VOUT_DLY;
				ovp_vout_dec_cnt = OVP_VOUT_DLY;
				/* Filter of hiccup condition entrance. */
				if(ovcrr_hiccup_in_cnt < OVCRR_HICCUP_IN_CNT_LIM)
				{
					ovcrr_hiccup_in_cnt ++;
				}
			}
			/* 
			 * Allow voltage under threshold during certain time before
			 * folding back.
			 */
			if(voltage_ctr.reference < BUCK_VOLTAGE_REF_TRHLD)
			{
				/* 
				 * If the output current has been higher than the limit
				 * for several iterations triggers the protection. 
				 * Voltage can still go lower in this mode.
				 */
				if(ovpwr_hiccup_in_cnt == 0)
				{
					current_ctr.ovp_state = true;
				}
				else
				{
					ovpwr_hiccup_in_cnt --;
				}
			}
			else
			{
				/* Filter of hiccup condition entrance. */
				if(ovpwr_hiccup_in_cnt < (uint32_t)OVPWR_HICCUP_IN_CNT_LIM)
				{
					ovpwr_hiccup_in_cnt ++;
				}
			}
			/* Synchronous to control IRQ timer. */
			ovp_vout_tick = (converter_ctr.time_tick >> OVP_VOUT_PRSCLR);
		}
	}
	/* Converter is in fault mode. */
	else
	{
		/* Synchronous to control IRQ timer. */
		if((converter_ctr.time_tick >> OVP_VOUT_PRSCLR) != ovp_vout_tick)
		{
			ovp_vout_inc_cnt = OVP_VOUT_DLY;
			ovp_vout_dec_cnt = OVP_VOUT_DLY;
			/* Filter of hiccup condition entrance. */
			if(ovpwr_hiccup_in_cnt < (uint32_t)OVPWR_HICCUP_IN_CNT_LIM)
			{
				ovpwr_hiccup_in_cnt ++;
			}
			/* Filter of hiccup condition entrance. */
			if(ovcrr_hiccup_in_cnt < OVCRR_HICCUP_IN_CNT_LIM)
			{
				ovcrr_hiccup_in_cnt ++;
			}
			/* Reset of flag to allow restart. */
			if((ovpwr_hiccup_in_cnt == (uint32_t)OVPWR_HICCUP_IN_CNT_LIM) && (ovcrr_hiccup_in_cnt == OVCRR_HICCUP_IN_CNT_LIM))
			{
				current_ctr.ovp_state = false;
			}	
			/* Synchronous to control IRQ timer. */
			ovp_vout_tick = (converter_ctr.time_tick >> OVP_VOUT_PRSCLR);
		}
	}
}
/*---------------------------------------------------------------------------*/
/**
 * \brief       Current ratio of the conduction times adjustment
 * \return      None
 */
#ifndef DOXYGEN_SKIP
__attribute__((section(".ram_code")))
#endif
static inline void buck_current_ratio_ctr()
{
	static uint16_t dt_AB_il_adjust; /* Value of dead time updated into the PWM. [CCU_clk] */
	static uint16_t dt_CD_il_adjust; /* Value of dead time updated into the PWM. [CCU_clk] */
	static uint16_t dt_AB_il_inc_cnt; /* Filter of dead time increment. [control_cyc] */
	static uint16_t dt_AB_il_decr_cnt; /* Filter of dead time decrement. [control_cyc] */
	static uint16_t dt_CD_il_inc_cnt; /* Filter of dead time increment. [control_cyc] */
	static uint16_t dt_CD_il_decr_cnt; /* Filter of dead time decrement. [control_cyc] */
	static uint16_t synch_on_inc_cnt; /* Filter of synchronous on time increment. [control_cyc] */
	static uint16_t synch_off_inc_cnt; /* Filter of synchronous off time increment. [control_cyc] */
	static uint32_t il_previous_tick; /* Input current measurement clock divider. [control_cyc] */
	uint16_t dt_AB_il_adjust_new; /* Calculated value of dead time in this iteration. [CCU_clk] */
	uint16_t dt_CD_il_adjust_new; /* Calculated value of dead time in this iteration. [CCU_clk] */
	uint16_t synch_ON_il_delay_new; /* Calculated value of synchronous on delay this iteration. [CCU_clk] */
	uint16_t synch_OFF_il_delay_new; /* Calculated value of synchronous off delay this iteration. [CCU_clk] */

    /* Output overcurrent has to be scaled with regard to the input voltage. */
	current_ctr.hiccup_io_limit = (converter_ctr.status & SOFT) ? HICCUP_SOFT_LIM : HICCUP_LIM;
	
	/* Time division of the controller clock for bridge deadtimes adjustment. */
	if((converter_ctr.time_tick >> ADST_DLY_PRSCLR) != il_previous_tick)
	{
		/* Decrement of dead time with increasing current, drain voltage resonates faster for higher loads. */
		dt_AB_il_adjust_new = ((current_ctr.adc_il_measure * parameters_RAM.bridge_A_B_il_factor) >> parameters_RAM.bridge_il_ratio);
		dt_CD_il_adjust_new = ((current_ctr.adc_il_measure * parameters_RAM.bridge_C_D_il_factor) >> parameters_RAM.bridge_il_ratio);
		/* 
		 * Limits the rate of change of the dt to avoid interactions with the
		 * control loop. 
		 */
		if(dt_AB_il_adjust_new > dt_AB_il_adjust)
		{
			if(dt_AB_il_inc_cnt > 0)
			{
				dt_AB_il_inc_cnt --;
			}
			else
			{
				/* Progressive change of dead time. */
				dt_AB_il_adjust ++;
				/* Reset of the change filter. */
				dt_AB_il_inc_cnt = DT_ADJST_DLY;
			}
			/* Reset of the change filter. */
			dt_AB_il_decr_cnt = DT_ADJST_DLY;
		}
		else if(dt_AB_il_adjust_new < dt_AB_il_adjust)
		{
			if(dt_AB_il_decr_cnt > 0)
			{
				dt_AB_il_decr_cnt --;
			}
			else
			{
				/* Progressive change of dead time. */
				dt_AB_il_adjust --;
				/* Reset of the change filter. */
				dt_AB_il_decr_cnt = DT_ADJST_DLY;
			}
			/* Reset of the change filter. */
			dt_AB_il_inc_cnt = DT_ADJST_DLY;
		}
		else
		{
			/* Reset of the change filter. */
			dt_AB_il_decr_cnt = DT_ADJST_DLY;
			dt_AB_il_inc_cnt = DT_ADJST_DLY;
		}
		
		/* 
		 * Limits the rate of change of the dt to avoid interactions with the
		 * control loop. 
		 */
		if(dt_CD_il_adjust_new > dt_CD_il_adjust)
		{
			if(dt_CD_il_inc_cnt > 0)
			{
				dt_CD_il_inc_cnt --;
			}
			else
			{
				/* Progressive change of dead time. */
				dt_CD_il_adjust ++;
				/* Reset of the change filter. */
				dt_CD_il_inc_cnt = DT_ADJST_DLY;
			}
			/* Reset of the change filter. */
			dt_CD_il_decr_cnt = DT_ADJST_DLY;
		}
		else if(dt_CD_il_adjust_new < dt_CD_il_adjust)
		{
			if(dt_CD_il_decr_cnt > 0)
			{
				dt_CD_il_decr_cnt --;
			}
			else
			{
				/* Progressive change of dead time. */
				dt_CD_il_adjust --;
				/* Reset of the change filter. */
				dt_CD_il_decr_cnt = DT_ADJST_DLY;
			}
			/* Reset of the change filter. */
			dt_CD_il_inc_cnt = DT_ADJST_DLY;
		}
		else
		{
			/* Reset of the change filter. */
			dt_CD_il_decr_cnt = DT_ADJST_DLY;
			dt_CD_il_inc_cnt = DT_ADJST_DLY;
		}
	}
	/* Checks whether dead time is still within a valid range. */
	current_ctr.dt_A_B = ((parameters_RAM.dead_time_A_B - dt_AB_il_adjust) > PWM_A_B_MIN_DT) ? (parameters_RAM.dead_time_A_B - dt_AB_il_adjust) : PWM_A_B_MIN_DT;
	current_ctr.dt_C_D = ((parameters_RAM.dead_time_C_D - PWM_C_D_CHAIN_DLY - dt_CD_il_adjust) > PWM_C_D_MIN_DT) ? (parameters_RAM.dead_time_C_D - PWM_C_D_CHAIN_DLY - dt_CD_il_adjust) : PWM_C_D_MIN_DT;

	/* 
	 * Adjustment of the conduction time of the synchronous. 
	 */
	if(voltage_ctr.error[0] < (-SYNCH_VO_LD_JMP))
	{
		/* Short reaction time to load jumps. */
		synch_ON_il_delay_new = ((current_ctr.adc_il_measure * parameters_RAM.synch_ON_il_factor) >> parameters_RAM.synch_ON_il_ratio);
		synch_OFF_il_delay_new = 0;
	}
	else
	{
		/* Steady state conditions. */
		synch_ON_il_delay_new = ((current_ctr.adc_il_measure * parameters_RAM.synch_ON_il_factor) >> parameters_RAM.synch_ON_il_ratio);
		synch_OFF_il_delay_new = ((current_ctr.adc_il_measure * parameters_RAM.synch_OFF_il_factor) >> parameters_RAM.synch_OFF_il_ratio);
	}
	/* Short reaction time to load jumps. */
	if(synch_ON_il_delay_new < (current_ctr.synch_il_ON - SYNCH_DLY_LD_JMP))
	{
		current_ctr.synch_il_ON -= SYNCH_DLY_LD_JMP;
	}
	/* Time division of the controller clock for adjustment of synch. timings. */
	if((converter_ctr.time_tick >> ADST_DLY_PRSCLR) != il_previous_tick)
	{
		/* Limits the rate of change of the dt when increasing. */
		if(synch_ON_il_delay_new > current_ctr.synch_il_ON)
		{
			if(synch_on_inc_cnt > 0)
			{
				synch_on_inc_cnt --;
			}
			else
			{
				/* Progressive change of dead time. */
				current_ctr.synch_il_ON ++;
				/* Reset of the change filter. */
				synch_on_inc_cnt = SYNCH_ADJST_DLY;
			}
		}
		else if(synch_ON_il_delay_new < current_ctr.synch_il_ON)
		{
			/* Progressive change of dead time. */
			current_ctr.synch_il_ON --;
			/* Reset of the change filter. */
			synch_on_inc_cnt = SYNCH_ADJST_DLY;
		}
		else
		{
			/* Reset of the change filter. */
			synch_on_inc_cnt = SYNCH_ADJST_DLY;
		}
	}
	/* Short reaction time to load jumps. */
	if(synch_OFF_il_delay_new < current_ctr.synch_il_OFF)
	{
		current_ctr.synch_il_OFF = synch_OFF_il_delay_new;
	}
	/* Time division of the controller clock */
	if((converter_ctr.time_tick >> ADST_DLY_PRSCLR) != il_previous_tick)
	{
		/* Limits the rate of change of the dt when increasing. */
		if(synch_OFF_il_delay_new > current_ctr.synch_il_OFF)
		{
			if(synch_off_inc_cnt > 0)
			{
				synch_off_inc_cnt --;
			}
			else
			{
				/* Progressive change of dead time. */
				current_ctr.synch_il_OFF ++;
				/* Reset of the change filter. */
				synch_off_inc_cnt = SYNCH_ADJST_DLY;
			}
		}
		else if(synch_OFF_il_delay_new < current_ctr.synch_il_OFF)
		{
			/* Progressive change of dead time. */
			current_ctr.synch_il_OFF --;
			/* Reset of the change filter. */
			synch_off_inc_cnt = SYNCH_ADJST_DLY;
		}
		else
		{
			/* Reset of the change filter. */
			synch_off_inc_cnt = SYNCH_ADJST_DLY;
		}
		il_previous_tick = (converter_ctr.time_tick >> ADST_DLY_PRSCLR);
	}
	/* Adjustment of the bridge dead times depending on the output current. */
    pwm_dt_adjust();
    /* Phase shift of PWM is controlled by the integrated DAC, not by the PR, CR... */
    PWM_A_B.ccu8_module_ptr->GCSS = PWM_A_B.shadow_txfr_msk | PWM_C.shadow_txfr_msk | PWM_D.shadow_txfr_msk;
}
/*---------------------------------------------------------------------------*/
/**
 * \brief	Initialization of the buck mode back from boost mode.
 * \return	None
 */
#ifndef DOXYGEN_SKIP
__attribute__((section(".ram_code")))
#endif
static inline void buck_mode_init()
{
	/* Replace control routines by buck converter ones. */
	converter_ctr.status &= ~BOOST_MODE;
	/* Set synchronous rectifiers in boost mode. */
	boost_to_buck_pwm_cfg();
}
#endif /* __CONTROLLER_BUCK_H_ */
/** @} */
